{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.7.8"
    },
    "colab": {
      "name": "MLAS_03_NeuralNets_Classification.ipynb",
      "provenance": []
    },
    "widgets": {
      "application/vnd.jupyter.widget-state+json": {
        "8d81ace9da7d4350a7cd70e3f72aacc8": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HBoxModel",
          "state": {
            "_view_name": "HBoxView",
            "_dom_classes": [],
            "_model_name": "HBoxModel",
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "box_style": "",
            "layout": "IPY_MODEL_0e794f3a81334795a216e9f10f405e3b",
            "_model_module": "@jupyter-widgets/controls",
            "children": [
              "IPY_MODEL_06e71dbc466444feb8eb13ec38341cf3",
              "IPY_MODEL_ca6e0a5e57a84aca9b4ff6035984c50b"
            ]
          }
        },
        "0e794f3a81334795a216e9f10f405e3b": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "06e71dbc466444feb8eb13ec38341cf3": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "FloatProgressModel",
          "state": {
            "_view_name": "ProgressView",
            "style": "IPY_MODEL_62204b1e00874ea1bcf588546dd401a6",
            "_dom_classes": [],
            "description": "",
            "_model_name": "FloatProgressModel",
            "bar_style": "success",
            "max": 1,
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "value": 1,
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "orientation": "horizontal",
            "min": 0,
            "description_tooltip": null,
            "_model_module": "@jupyter-widgets/controls",
            "layout": "IPY_MODEL_7e2e5742994444e69d7d3b9f8f044e41"
          }
        },
        "ca6e0a5e57a84aca9b4ff6035984c50b": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "state": {
            "_view_name": "HTMLView",
            "style": "IPY_MODEL_f4a87365703045bb8c279fcb1ff1d533",
            "_dom_classes": [],
            "description": "",
            "_model_name": "HTMLModel",
            "placeholder": "​",
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "value": " 9920512/? [00:01&lt;00:00, 6557060.41it/s]",
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "description_tooltip": null,
            "_model_module": "@jupyter-widgets/controls",
            "layout": "IPY_MODEL_02451cd6cc804ff8b406393507fbb150"
          }
        },
        "62204b1e00874ea1bcf588546dd401a6": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ProgressStyleModel",
          "state": {
            "_view_name": "StyleView",
            "_model_name": "ProgressStyleModel",
            "description_width": "initial",
            "_view_module": "@jupyter-widgets/base",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.2.0",
            "bar_color": null,
            "_model_module": "@jupyter-widgets/controls"
          }
        },
        "7e2e5742994444e69d7d3b9f8f044e41": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "f4a87365703045bb8c279fcb1ff1d533": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_view_name": "StyleView",
            "_model_name": "DescriptionStyleModel",
            "description_width": "",
            "_view_module": "@jupyter-widgets/base",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.2.0",
            "_model_module": "@jupyter-widgets/controls"
          }
        },
        "02451cd6cc804ff8b406393507fbb150": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "03b19ff8c63b48e49bdb195fc9577575": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HBoxModel",
          "state": {
            "_view_name": "HBoxView",
            "_dom_classes": [],
            "_model_name": "HBoxModel",
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "box_style": "",
            "layout": "IPY_MODEL_6cfd0a7280a2408e8790ef2650ec2935",
            "_model_module": "@jupyter-widgets/controls",
            "children": [
              "IPY_MODEL_ee938098bff044cf95b88af20fbfda31",
              "IPY_MODEL_b13bb32842444b34898f1d702072f8f3"
            ]
          }
        },
        "6cfd0a7280a2408e8790ef2650ec2935": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "ee938098bff044cf95b88af20fbfda31": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "FloatProgressModel",
          "state": {
            "_view_name": "ProgressView",
            "style": "IPY_MODEL_a79c0a8d13824e6485a584677e4e0d36",
            "_dom_classes": [],
            "description": "",
            "_model_name": "FloatProgressModel",
            "bar_style": "success",
            "max": 1,
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "value": 1,
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "orientation": "horizontal",
            "min": 0,
            "description_tooltip": null,
            "_model_module": "@jupyter-widgets/controls",
            "layout": "IPY_MODEL_cce5983ad6294dca96e5628ec2b1f3b2"
          }
        },
        "b13bb32842444b34898f1d702072f8f3": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "state": {
            "_view_name": "HTMLView",
            "style": "IPY_MODEL_b106afbf78394413a6cd31d432270e3d",
            "_dom_classes": [],
            "description": "",
            "_model_name": "HTMLModel",
            "placeholder": "​",
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "value": " 32768/? [00:00&lt;00:00, 40578.13it/s]",
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "description_tooltip": null,
            "_model_module": "@jupyter-widgets/controls",
            "layout": "IPY_MODEL_76b3ca904a2c45259346dc96ad26a6b6"
          }
        },
        "a79c0a8d13824e6485a584677e4e0d36": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ProgressStyleModel",
          "state": {
            "_view_name": "StyleView",
            "_model_name": "ProgressStyleModel",
            "description_width": "initial",
            "_view_module": "@jupyter-widgets/base",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.2.0",
            "bar_color": null,
            "_model_module": "@jupyter-widgets/controls"
          }
        },
        "cce5983ad6294dca96e5628ec2b1f3b2": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "b106afbf78394413a6cd31d432270e3d": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_view_name": "StyleView",
            "_model_name": "DescriptionStyleModel",
            "description_width": "",
            "_view_module": "@jupyter-widgets/base",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.2.0",
            "_model_module": "@jupyter-widgets/controls"
          }
        },
        "76b3ca904a2c45259346dc96ad26a6b6": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "7980fb648e45461c9a46f4954c8e2ea5": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HBoxModel",
          "state": {
            "_view_name": "HBoxView",
            "_dom_classes": [],
            "_model_name": "HBoxModel",
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "box_style": "",
            "layout": "IPY_MODEL_e475f4e9b803468aa25b3e4f82b4be8c",
            "_model_module": "@jupyter-widgets/controls",
            "children": [
              "IPY_MODEL_2c7e63fdfbe44370b5c1745dffcbded7",
              "IPY_MODEL_7db3fc05b8454682bd8dc165f20690ac"
            ]
          }
        },
        "e475f4e9b803468aa25b3e4f82b4be8c": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "2c7e63fdfbe44370b5c1745dffcbded7": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "FloatProgressModel",
          "state": {
            "_view_name": "ProgressView",
            "style": "IPY_MODEL_6e28ae1a96864ffbbc950ccd6bd33015",
            "_dom_classes": [],
            "description": "",
            "_model_name": "FloatProgressModel",
            "bar_style": "success",
            "max": 1,
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "value": 1,
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "orientation": "horizontal",
            "min": 0,
            "description_tooltip": null,
            "_model_module": "@jupyter-widgets/controls",
            "layout": "IPY_MODEL_2c8adeb602604c42abd6193eee27c112"
          }
        },
        "7db3fc05b8454682bd8dc165f20690ac": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "state": {
            "_view_name": "HTMLView",
            "style": "IPY_MODEL_882e912bc97141589a28a7b2d975d252",
            "_dom_classes": [],
            "description": "",
            "_model_name": "HTMLModel",
            "placeholder": "​",
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "value": " 1654784/? [00:00&lt;00:00, 2610642.48it/s]",
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "description_tooltip": null,
            "_model_module": "@jupyter-widgets/controls",
            "layout": "IPY_MODEL_48240401f50645b8970b30b0b740b6c6"
          }
        },
        "6e28ae1a96864ffbbc950ccd6bd33015": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ProgressStyleModel",
          "state": {
            "_view_name": "StyleView",
            "_model_name": "ProgressStyleModel",
            "description_width": "initial",
            "_view_module": "@jupyter-widgets/base",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.2.0",
            "bar_color": null,
            "_model_module": "@jupyter-widgets/controls"
          }
        },
        "2c8adeb602604c42abd6193eee27c112": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "882e912bc97141589a28a7b2d975d252": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_view_name": "StyleView",
            "_model_name": "DescriptionStyleModel",
            "description_width": "",
            "_view_module": "@jupyter-widgets/base",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.2.0",
            "_model_module": "@jupyter-widgets/controls"
          }
        },
        "48240401f50645b8970b30b0b740b6c6": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "4d3c5106f21548778666bddecc30af46": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HBoxModel",
          "state": {
            "_view_name": "HBoxView",
            "_dom_classes": [],
            "_model_name": "HBoxModel",
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "box_style": "",
            "layout": "IPY_MODEL_0893b4e3182f45caaf76663846f82d7a",
            "_model_module": "@jupyter-widgets/controls",
            "children": [
              "IPY_MODEL_dd57f61e43aa43b8b1679b530e353e5c",
              "IPY_MODEL_814045b582d44396869cf172eb9ffb69"
            ]
          }
        },
        "0893b4e3182f45caaf76663846f82d7a": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "dd57f61e43aa43b8b1679b530e353e5c": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "FloatProgressModel",
          "state": {
            "_view_name": "ProgressView",
            "style": "IPY_MODEL_172bc3033b334999976afb6fdeb65087",
            "_dom_classes": [],
            "description": "",
            "_model_name": "FloatProgressModel",
            "bar_style": "success",
            "max": 1,
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "value": 1,
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "orientation": "horizontal",
            "min": 0,
            "description_tooltip": null,
            "_model_module": "@jupyter-widgets/controls",
            "layout": "IPY_MODEL_1aaf4bfc08a342ed8e31830da7406fc0"
          }
        },
        "814045b582d44396869cf172eb9ffb69": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "state": {
            "_view_name": "HTMLView",
            "style": "IPY_MODEL_84a2bbae3b5c4f2da8e5002fb698d074",
            "_dom_classes": [],
            "description": "",
            "_model_name": "HTMLModel",
            "placeholder": "​",
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "value": " 8192/? [00:00&lt;00:00, 23034.77it/s]",
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "description_tooltip": null,
            "_model_module": "@jupyter-widgets/controls",
            "layout": "IPY_MODEL_92428e0853634af4a74738e2e5575297"
          }
        },
        "172bc3033b334999976afb6fdeb65087": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ProgressStyleModel",
          "state": {
            "_view_name": "StyleView",
            "_model_name": "ProgressStyleModel",
            "description_width": "initial",
            "_view_module": "@jupyter-widgets/base",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.2.0",
            "bar_color": null,
            "_model_module": "@jupyter-widgets/controls"
          }
        },
        "1aaf4bfc08a342ed8e31830da7406fc0": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "84a2bbae3b5c4f2da8e5002fb698d074": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_view_name": "StyleView",
            "_model_name": "DescriptionStyleModel",
            "description_width": "",
            "_view_module": "@jupyter-widgets/base",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.2.0",
            "_model_module": "@jupyter-widgets/controls"
          }
        },
        "92428e0853634af4a74738e2e5575297": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        }
      }
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "PDMVVv6JEVuR"
      },
      "source": [
        "<center>\n",
        "    <img src=\"https://github.com/GuitarsAI/MLfAS/blob/master/images/mlfasp.png?raw=1\">\n",
        "</center>\n",
        "\n",
        "#### Prof. Dr. -Ing. Gerald Schuller <br> Jupyter Notebook: Renato Profeta\n",
        "\n",
        "[Applied Media Systems Group](https://www.tu-ilmenau.de/en/applied-media-systems-group/) <br>\n",
        "[Technische Universität Ilmenau](https://www.tu-ilmenau.de/)"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "JbufRPgmEdtK",
        "outputId": "029a530b-21bd-48e6-f945-aea3c27096a4",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "# Configuration for Google Colab Runtime Environment\n",
        "\n",
        "if 'google.colab' in str(get_ipython()):\n",
        "  print('Running on CoLab')\n",
        "  !mkdir ./images\n",
        "else:\n",
        "  print('Not running on CoLab')"
      ],
      "execution_count": 2,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Running on CoLab\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "hide_input": true,
        "id": "hvvnc_keEVuS"
      },
      "source": [
        "# Neural Networks for Classification"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "hide_input": true,
        "id": "beBQj1CdEVuT",
        "outputId": "9d31d2a9-e6d9-474e-88ab-c03444d0d944",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 336
        }
      },
      "source": [
        "%%html\n",
        "<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/Ld0cwTiXrU0?rel=0\" frameborder=\"0\" allow=\"accelerometer; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>"
      ],
      "execution_count": 3,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/Ld0cwTiXrU0?rel=0\" frameborder=\"0\" allow=\"accelerometer; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "hide_input": true,
        "id": "PftlfR86EVuX"
      },
      "source": [
        "We saw in neural networks for detection, that they need to detect if a pattern is present or not. For the classification tasks we have a class of patterns, and we know that a pattern of one of the classes has to be present. The network has to decide which class. A classical application is the classification of handwritten digits. The network input are images of handwritten digits, and each image belongs to one of the 10 digit classes, 0 to 9.\n",
        "\n",
        "The network usually has as many outputs as classes (10 in the digit example), and each output might represent the probability that the image at the networks input belongs to the corresponding class. Since we know that it must be one of the 10 digits, the probabilities must add up to 1.\n",
        "\n",
        "A classical data base for this example is the MNIST database (Modified National Institute of Standards and Technology database):"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "hide_input": true,
        "id": "v9p5lvMrEVuX",
        "outputId": "b8bcd24a-bd17-4806-febc-e483d953a682",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 625
        }
      },
      "source": [
        "%%html\n",
        "<iframe src=\"https://en.wikipedia.org/wiki/MNIST_database\" width=\"900\" height=\"600\"></iframe>"
      ],
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "<iframe src=\"https://en.wikipedia.org/wiki/MNIST_database\" width=\"900\" height=\"600\"></iframe>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "hide_input": false,
        "id": "kh4dwmQ8EVub"
      },
      "source": [
        "It contains 60000 gray-scale images of handwritten images of size 28x28 pixels.\n",
        "\n",
        "Python has a function to directly access and download these images, in `torchvision.datasets.MNIST`.\n",
        "\n",
        "Look at our example:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "hide_input": true,
        "id": "PsVkXFHVEVuc",
        "outputId": "9a189a7c-0afd-4d12-bc9d-9c893a3abc14",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 336
        }
      },
      "source": [
        "%%html\n",
        "<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/h5dliJHNqFg?rel=0\" frameborder=\"0\" allow=\"accelerometer; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>"
      ],
      "execution_count": 5,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/h5dliJHNqFg?rel=0\" frameborder=\"0\" allow=\"accelerometer; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "sYu73swiEVue"
      },
      "source": [
        "It uses `train_loader = torch.utils.data.DataLoader(torchvision.datasets.MNIST(..)` to load **training set** with 100 random images and target classes, and a **test set** of 10 random images and target classes.\n",
        "\n",
        "After loading and then reading in the training set with the `next(..)` function, we can check the resulting data type with a print statement and with the `.type()` function: `print( \"X_train.type()=\",X_train.type(),\"y_train.type()=\",y_train.type())`\n",
        "\n",
        "We obtain `X_train.type()= torch.FloatTensor y_train.type()=torch.LongTensor`\n",
        "\n",
        "Observe that the input signal, the images, have the type `torch.FloatTensor`, whereas the target, the correct digit class indices, have the type torch.LongTensor! **This difference in Types** becomes important when we apply a **loss function.**\n",
        "\n",
        "Next we have another \"print\" line to check for the shape and content of our data tensors:\n",
        "```python\n",
        "print(\"batch_idx=\", batch_idx, \"X_train.shape=\",\n",
        "      X_train.shape, \"y_train.shape=\", \n",
        "      y_train.shape, \"y_train=\",y_train)```\n",
        "      \n",
        "which prints out: \n",
        "`batch_idx= 0 X_train.shape= torch.Size([100, 1, 28, 28])\n",
        "y_train.shape= torch.Size([100])`\n",
        "\n",
        "\"X_train.shape= torch.Size([100, 1, 28, 28])\" shows that the first index is for the image (100 images), the 2nd index is for the batch and only contains 1 batch, and the remaining 2 indices are for the 28 pixels vertically and horizontally, respectively.\n",
        "\n",
        "\"y_train.shape= torch.Size([100])\" shows the shape of the target, which is a 1-dimensional array of 100 entries. It is one number (the correct digit) for each image. This can also be seen in the final part of the printout:\n",
        "\n",
        "`y_train= tensor([ 5, 7, 1, 2, 2, 0, 1, 0, 3, 4, 2, 2, 6, 4,\n",
        "9, 2, 6, 3, 1, 6, 1, 8, 6, 7, 1, 0, 5, 6,\n",
        "3, 7, 6, 6, 1, 2, 5, 5, 0, 1, 6, 3, 7, 4,\n",
        "7, 9, 0, 5, 5, 2, 3, 6, 8, 1, 6, 1, 4, 5,\n",
        "9, 5, 4, 1, 5, 6, 2, 9, 2, 1, 7, 7, 1, 1,\n",
        "6, 6, 2, 2, 6, 7, 9, 0, 7, 9, 5, 3, 1, 6,\n",
        "0, 3, 8, 8, 2, 4, 1, 9, 4, 3, 7, 5, 7, 5,\n",
        "6, 2])`\n",
        "\n",
        "Then we have to define our neural network as \"Class DenseNet(..)\". We take 2 fully connected layers (the nn.Linear), with bias and with a relu activation function only after the first layer:\n",
        "\n",
        "```python\n",
        "# define the neural network model\n",
        "class DenseNet(nn.Module):\n",
        "    def __init__(self):\n",
        "        super(DenseNet, self).__init__()\n",
        "        self.layer1=nn.Sequential(nn.Linear(in_features=num_pixels,\n",
        "        out_features=num_pixels))\n",
        "        self.layer2=nn.Sequential(nn.Linear(in_features=num_pixels,\n",
        "        out_features=num_classes))\n",
        "        \n",
        "    def forward(self, x):\n",
        "        x = F.relu(self.layer1(x)) #First layer with activation function\n",
        "        x = self.layer2(x) #Second layer\n",
        "        #x = torch.nn.softmax(x)\n",
        "        return x\n",
        "```\n",
        "    \n",
        "Here we choose the size of the hidden layer (the output of layer 1) the same as the number of pixels at the input, but it could also be a different number.\n",
        "\n",
        "Our program plots the first 4 images of the training set. For that we need to know the meaning of the indices (see above).\n",
        "\n",
        "For instance for the 2nd image in the set, we plot:\n",
        "`plt.imshow(X_train[1,0], cmap=plt.get_cmap('gray'))`\n",
        "\n",
        "Index \"1\" is the index of the image, index \"0\" is for the current batch or set of images (in our example we only have batch 0), and the remaining 2 indices to the right, which are not seen here, are the image pixel indices. An example set of images is:\n",
        "\n",
        "<img src='https://github.com/GuitarsAI/MLfAS/blob/master/images/03_01_imagesExample.png?raw=1' width='500'>\n",
        "\n",
        "After showing the images, we can reshape or flatten them into 1-dimensional arrays to make them suitable as input to our fully connected linear layers (remember, they only take 1-dimensional inputs). For that, we use the `.view` function:\n",
        "\n",
        "`#Flatten the images:\n",
        "X_train = X_train.view(X_train.shape[0], num_pixels)`\n",
        "\n",
        "where `X_train.shape[0]` is the number of images in the batch.\n",
        "\n",
        "Observe that we don't need to reshape the target, because that is already a 1-dimensional array of the correct classes.\n",
        "\n",
        "After showing the images, the program initialized our neural network model with:\n",
        "`model = DenseNet()#.to('cpu')`\n",
        "\n",
        "Then it defines the loss function with:\n",
        "`loss_fn = nn.CrossEntropyLoss()`"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9woWInWaEVuf"
      },
      "source": [
        "The **\"CrossEntropyLoss\"** is made for **classification** tasks, hence it expects the data type `torch.FloatTensor` from the 10 outputs of our neural network (which fits), and `torch.LongTensor` as data type for the target data, which again fits! (also look at: https://discuss.pytorch.org/t/runtimeerror-expected-object-of-type-torch-longtensor-but-found-type-torch-floattensor/23289)\n",
        "\n",
        "Go to https://pytorch.org/docs/stable/nn.html and search in the website for `nn.CrossEntropyLoss`. There you can find more detail about its definition."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "hide_input": true,
        "id": "hKbUPPgAEVuf",
        "outputId": "5be26b6e-b74b-49ae-c5e1-55febce43bf9",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 336
        }
      },
      "source": [
        "%%html\n",
        "<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/6jdwKxurqK4?rel=0\" frameborder=\"0\" allow=\"accelerometer; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>"
      ],
      "execution_count": 6,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/6jdwKxurqK4?rel=0\" frameborder=\"0\" allow=\"accelerometer; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "hide_input": true,
        "id": "YsLCLuD7EVui",
        "outputId": "73b71741-9fbf-43b5-f852-fbbfd9553287",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 625
        }
      },
      "source": [
        "%%html\n",
        "<iframe src=\"https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html#torch.nn.CrossEntropyLoss\" width=\"900\" height=\"600\"></iframe>"
      ],
      "execution_count": 7,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "<iframe src=\"https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html#torch.nn.CrossEntropyLoss\" width=\"900\" height=\"600\"></iframe>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "8UEXfq65EVul"
      },
      "source": [
        "It basically first applies a SoftMax function to the 10 outputs of our neural network, and turns them into probabilities, such that they always sum up to 1 (it also applies a logarithm because that is part of the cross entropy calculation, and to make the optimization more precise for very small values). \n",
        "\n",
        "It also turns the target data into probabilities of 10 classes. It assigns the correct class a probability of 1, and to the incorrect classes a probability of 0. The it applies the Cross Entropy (https://en.wikipedia.org/wiki/Cross_entropy) to these two resulting probability distributions. The Cross Entropy gives a **measure about how different 2 probability distributions are.**\n",
        "\n",
        "The cross entropy between two distributions *p(x)* and *q(x)* over classes x is defined as:\n",
        "\n",
        "$$\\large\n",
        "H(p,q)=- \\sum_x p(x) \\log(q(x))$$\n",
        "\n",
        "It can be interpreted as the number of bits needed to describe a second probability distribution based on a first probability distribution. If they are identical, then we need 0 bits, and we minimized the Cross Entropy. Now *p(x)* is our target distribution, which is 1 for the correct class and 0 elsewhere. Hence the sum degenerates to just a single summand for the correct class *x=c* , and it becomes,\n",
        "\n",
        "$$\\large\n",
        "H(p,q)= - \\log(q(c))$$\n",
        "\n",
        "where *q(c)* is the output of our network for the correct class *c*.\n",
        "\n",
        "<cite>(see also the book by Eugene Charniak: \"Introduction to Deep Learning\", MIT Press, 2018.)</cite>\n",
        "\n",
        "Hence after training or optimization the probability distribution of our network (after Softmax) should be as similar as possible to the distribution of the target.\n",
        "\n",
        "When we apply the trained network (which is called **\"inference\"**, as opposed to **\"training\"**), instead of the *Softmax* we can simply take the argmax function, which returns the index with the largest output (or probability).\n",
        "\n",
        "Next we define the optimizer for the training, with,\n",
        "`optimizer = torch.optim.Adam(model.parameters())`\n",
        "\n",
        "As before, \"Adam\" is a popular and effective optimizer for neural networks (for \"Adaptive Moments\" and is a variation\n",
        "of Stochastic Gradient Descent, see e.g. in https://towardsdatascience.com/adam-latest-trends-indeep-learning-optimization-6be9a291375c).\n",
        "\n",
        "In our case we obtain a very fast optimization with only 10 \"epochs\" (iterations), with the decreasing loss function as in this printout:\n",
        "\n",
        "`0 2.32210111618042\n",
        "2 1.169947624206543\n",
        "4 0.5694917440414429\n",
        "6 0.28307318687438965\n",
        "8 0.1408798098564148`\n",
        "\n",
        "Finally we compute the loss on our test set of 10 images:\n",
        "\n",
        "`Loss on the test set: tensor(0.4930)`\n",
        "\n",
        "which is clearly worse than on our training set (where we reached about 0.14). We also test the performance on an example image from the test set, at \"inference\" using the argmax function. It shows an image from the test set, and predicts the corresponding class.\n",
        "\n",
        "The program first shows the image to be recognized:\n",
        "\n",
        "<img src='https://github.com/GuitarsAI/MLfAS/blob/master/images/03_02_imageEx.png?raw=1' width='500'>\n",
        "\n",
        "The corresponding printout from the prediction during inference is `prediction= tensor(8)` where the \"8\" is the class, that the network is predicting the input image belonging to (the recognized digit). The image is usually correctly classified (if the human observer also recognizes the digit 8 in the image)!\n",
        "\n",
        "**Observe** that the network **always outputs a number for a digit**, even when the image **does not contain a digit.**\n",
        "\n",
        "We could fix this by introducing a class with label \"no digit\", for which we also would need training data, which makes it difficult."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "upECHM1dEVul"
      },
      "source": [
        "## PyTorch Example Complete"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "hide_input": true,
        "id": "cKXDkxSREVul",
        "outputId": "f8ed77f6-245d-4602-85fa-1d89136ded1e",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 336
        }
      },
      "source": [
        "%%html\n",
        "<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/4xRcB4jB4-M?rel=0\" frameborder=\"0\" allow=\"accelerometer; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>"
      ],
      "execution_count": 8,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/4xRcB4jB4-M?rel=0\" frameborder=\"0\" allow=\"accelerometer; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "hide_input": false,
        "id": "3sZFqce-EVup",
        "outputId": "154bfff0-2b85-48fc-cbac-a5c40aa1b9aa",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 1000,
          "referenced_widgets": [
            "8d81ace9da7d4350a7cd70e3f72aacc8",
            "0e794f3a81334795a216e9f10f405e3b",
            "06e71dbc466444feb8eb13ec38341cf3",
            "ca6e0a5e57a84aca9b4ff6035984c50b",
            "62204b1e00874ea1bcf588546dd401a6",
            "7e2e5742994444e69d7d3b9f8f044e41",
            "f4a87365703045bb8c279fcb1ff1d533",
            "02451cd6cc804ff8b406393507fbb150",
            "03b19ff8c63b48e49bdb195fc9577575",
            "6cfd0a7280a2408e8790ef2650ec2935",
            "ee938098bff044cf95b88af20fbfda31",
            "b13bb32842444b34898f1d702072f8f3",
            "a79c0a8d13824e6485a584677e4e0d36",
            "cce5983ad6294dca96e5628ec2b1f3b2",
            "b106afbf78394413a6cd31d432270e3d",
            "76b3ca904a2c45259346dc96ad26a6b6",
            "7980fb648e45461c9a46f4954c8e2ea5",
            "e475f4e9b803468aa25b3e4f82b4be8c",
            "2c7e63fdfbe44370b5c1745dffcbded7",
            "7db3fc05b8454682bd8dc165f20690ac",
            "6e28ae1a96864ffbbc950ccd6bd33015",
            "2c8adeb602604c42abd6193eee27c112",
            "882e912bc97141589a28a7b2d975d252",
            "48240401f50645b8970b30b0b740b6c6",
            "4d3c5106f21548778666bddecc30af46",
            "0893b4e3182f45caaf76663846f82d7a",
            "dd57f61e43aa43b8b1679b530e353e5c",
            "814045b582d44396869cf172eb9ffb69",
            "172bc3033b334999976afb6fdeb65087",
            "1aaf4bfc08a342ed8e31830da7406fc0",
            "84a2bbae3b5c4f2da8e5002fb698d074",
            "92428e0853634af4a74738e2e5575297"
          ]
        }
      },
      "source": [
        "#from: https://machinelearningmastery.com/handwritten-digit-recognition-using-convolutional-neural-networks-python-keras/\n",
        "#https://pytorch.org/docs/stable/torchvision/datasets.html#mnist\n",
        "#Translated to PyTorch and modified to a simple fully connected network,\n",
        "#by Gerald Schuller, October 2019\n",
        "\n",
        "import numpy\n",
        "import matplotlib.pyplot as plt\n",
        "import torch\n",
        "import torchvision\n",
        "import torch.nn.functional as F\n",
        "import torch.nn as nn\n",
        "import time\n",
        "\n",
        "device='cpu'\n",
        "#device='cuda'\n",
        "\n",
        "# define the neural network model\n",
        "class DenseNet(nn.Module):\n",
        "    def __init__(self):\n",
        "        super(DenseNet, self).__init__()\n",
        "        self.layer1=nn.Sequential(nn.Linear(in_features=num_pixels, out_features=num_pixels))\n",
        "        self.layer2=nn.Sequential(nn.Linear(in_features=num_pixels, out_features=num_classes))\n",
        "      \n",
        "   \n",
        "    def forward(self, x):\n",
        "        x = F.relu(self.layer1(x))  #First layer with activation function\n",
        "        x = self.layer2(x)   #Second layer\n",
        "        #x = torch.nn.Softmax(x)\n",
        "        return x\n",
        "\n",
        "\n",
        "\n",
        "batch_size_train = 100\n",
        "batch_size_test = 10\n",
        "num_classes = 10  #10 classes according to the 10 possible digits 0,...,9\n",
        "\n",
        "train_loader = torch.utils.data.DataLoader(\n",
        "    torchvision.datasets.MNIST('~/Downloads/MNISTfiles/', \n",
        "    train=True, download=True,\n",
        "    transform=torchvision.transforms.Compose([torchvision.transforms.ToTensor(),\n",
        "    torchvision.transforms.Normalize((0.1307,), (0.3081,))])),\n",
        "    batch_size=batch_size_train, shuffle=True)\n",
        "#the Normalize() arguments are mean and standard deviation.\n",
        "\n",
        "test_loader = torch.utils.data.DataLoader(\n",
        "    torchvision.datasets.MNIST('~/Downloads/MNISTfiles/', \n",
        "                               train=False, download=True,\n",
        "                               transform=torchvision.transforms.Compose(\n",
        "                                   [torchvision.transforms.ToTensor(),\n",
        "                                    torchvision.transforms.Normalize((0.1307,), (0.3081,))])),\n",
        "    batch_size=batch_size_test, shuffle=True)\n",
        "\n",
        "\n",
        "examples = enumerate(train_loader)\n",
        "# Plot ad hoc mnist instances\n",
        "\n",
        "# load (downloaded if needed) the MNIST dataset\n",
        "#(X_train, y_train), (X_test, y_test) = mnist.load_data()\n",
        "#one batch of 100 images:\n",
        "batch_idx, (X_train, y_train) = next(examples)\n",
        "print( \"X_train.type()=\",X_train.type(), \"y_train.type()=\",y_train.type())\n",
        "print(\"batch_idx=\", batch_idx, \"X_train.shape=\", X_train.shape, \"y_train.shape=\", y_train.shape, \"y_train=\", y_train)\n",
        "examples = enumerate(test_loader)\n",
        "#one batch of 100 images:\n",
        "batch_idx, (X_test, y_test) = next(examples)\n",
        "\n",
        "# plot 4 images as gray scale\n",
        "plt.subplot(221)\n",
        "plt.title(\"Some Images of the Trainigs Set\")\n",
        "plt.imshow(X_train[0,0], cmap=plt.get_cmap('gray'))\n",
        "plt.subplot(222)\n",
        "plt.imshow(X_train[1,0], cmap=plt.get_cmap('gray'))\n",
        "plt.subplot(223)\n",
        "plt.imshow(X_train[2,0], cmap=plt.get_cmap('gray'))\n",
        "plt.subplot(224)\n",
        "plt.imshow(X_train[3,0], cmap=plt.get_cmap('gray'))\n",
        "# show the plot\n",
        "plt.show()\n",
        "\n",
        "\n",
        "X_testunflat=X_test.clone() #keep original for imshow later\n",
        "# flatten 28*28 images to a 784 vector for each image\n",
        "num_pixels = X_train.shape[2] * X_train.shape[3]\n",
        "\n",
        "\n",
        "#Flatten the images:\n",
        "X_train = X_train.view(X_train.shape[0], num_pixels)\n",
        "print(\"X_train.shape=\",X_train.shape)\n",
        "X_test = X_test.reshape(X_test.shape[0], num_pixels)\n",
        "print(\"X_test.shape=\",X_test.shape)\n",
        "\n",
        "# normalize inputs from 0-255 to 0-1\n",
        "#X_train = X_train / 255\n",
        "#X_test = X_test / 255\n",
        "\n",
        "# one hot encode outputs\n",
        "#y_train = np_utils.to_categorical(y_train)\n",
        "#y_test = np_utils.to_categorical(y_test)\n",
        "\n",
        "   \n",
        "# build the model\n",
        "print(\"Generate Model:\")\n",
        "model = DenseNet()#.to('cpu')\n",
        "    \n",
        "loss_fn = nn.CrossEntropyLoss()\n",
        "#learning_rate = 1e-4\n",
        "optimizer = torch.optim.Adam(model.parameters())#, lr=learning_rate)\n",
        "\n",
        "# Fit the model\n",
        "X_train=X_train.to(device)\n",
        "y_train=y_train.to(device)\n",
        "starttime=time.time()\n",
        "for epoch in range(10):\n",
        "    Ypred=model(X_train)\n",
        "    loss=loss_fn(Ypred, y_train)\n",
        "    if epoch%2==0:\n",
        "        print(epoch, loss.item())\n",
        "    optimizer.zero_grad()\n",
        "    loss.backward()\n",
        "    optimizer.step()\n",
        "       \n",
        "endtime=time.time()\n",
        "print(\"Duration of optimization:\", endtime-starttime)\n",
        "#model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=2, batch_size=200, verbose=2)\n",
        "# Final evaluation of the model\n",
        "Ypred=model(X_test)\n",
        "loss=loss_fn(Ypred, y_test)\n",
        "#scores = model.forward(X_test, y_test, verbose=0)\n",
        "print(\"Loss on the test set:\", loss)\n",
        "\n",
        "torch.save({'model_state_dict': model.state_dict(),\n",
        "       'optimizer_state_dict': optimizer.state_dict()}, \"mnistexample_pytorch_weights.torch\")\n",
        "print(\"Wrote to mnistexample_pytorch_weights.torch\")\n",
        "\n",
        "\n",
        "#\"Inference\", predict an example digit test image:\n",
        "plt.imshow(X_testunflat[1,0], cmap=plt.get_cmap('gray'))\n",
        "plt.title(\"A Digit Image to Regognize as a Test (predicted digit in the shell)\")\n",
        "\n",
        "sample=X_test[1,:]\n",
        "print(\"sample.shape=\", sample.shape)\n",
        "Ypred=model(sample)\n",
        "print(\"Test Ypred=\", Ypred)\n",
        "prediction=torch.argmax(Ypred) #use argmax as the class with the largest output\n",
        "print(\"prediction=\", prediction)\n",
        "\n",
        "plt.show()"
      ],
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz to /root/Downloads/MNISTfiles/MNIST/raw/train-images-idx3-ubyte.gz\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "display_data",
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "8d81ace9da7d4350a7cd70e3f72aacc8",
              "version_minor": 0,
              "version_major": 2
            },
            "text/plain": [
              "HBox(children=(FloatProgress(value=1.0, bar_style='info', max=1.0), HTML(value='')))"
            ]
          },
          "metadata": {
            "tags": []
          }
        },
        {
          "output_type": "stream",
          "text": [
            "Extracting /root/Downloads/MNISTfiles/MNIST/raw/train-images-idx3-ubyte.gz to /root/Downloads/MNISTfiles/MNIST/raw\n",
            "Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz to /root/Downloads/MNISTfiles/MNIST/raw/train-labels-idx1-ubyte.gz\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "display_data",
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "03b19ff8c63b48e49bdb195fc9577575",
              "version_minor": 0,
              "version_major": 2
            },
            "text/plain": [
              "HBox(children=(FloatProgress(value=1.0, bar_style='info', max=1.0), HTML(value='')))"
            ]
          },
          "metadata": {
            "tags": []
          }
        },
        {
          "output_type": "stream",
          "text": [
            "Extracting /root/Downloads/MNISTfiles/MNIST/raw/train-labels-idx1-ubyte.gz to /root/Downloads/MNISTfiles/MNIST/raw\n",
            "Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz to /root/Downloads/MNISTfiles/MNIST/raw/t10k-images-idx3-ubyte.gz\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "display_data",
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "7980fb648e45461c9a46f4954c8e2ea5",
              "version_minor": 0,
              "version_major": 2
            },
            "text/plain": [
              "HBox(children=(FloatProgress(value=1.0, bar_style='info', max=1.0), HTML(value='')))"
            ]
          },
          "metadata": {
            "tags": []
          }
        },
        {
          "output_type": "stream",
          "text": [
            "Extracting /root/Downloads/MNISTfiles/MNIST/raw/t10k-images-idx3-ubyte.gz to /root/Downloads/MNISTfiles/MNIST/raw\n",
            "Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz to /root/Downloads/MNISTfiles/MNIST/raw/t10k-labels-idx1-ubyte.gz\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "display_data",
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "4d3c5106f21548778666bddecc30af46",
              "version_minor": 0,
              "version_major": 2
            },
            "text/plain": [
              "HBox(children=(FloatProgress(value=1.0, bar_style='info', max=1.0), HTML(value='')))"
            ]
          },
          "metadata": {
            "tags": []
          }
        },
        {
          "output_type": "stream",
          "text": [
            "Extracting /root/Downloads/MNISTfiles/MNIST/raw/t10k-labels-idx1-ubyte.gz to /root/Downloads/MNISTfiles/MNIST/raw\n",
            "Processing...\n",
            "Done!\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.6/dist-packages/torchvision/datasets/mnist.py:469: UserWarning: The given NumPy array is not writeable, and PyTorch does not support non-writeable tensors. This means you can write to the underlying (supposedly non-writeable) NumPy array using the tensor. You may want to copy the array to protect its data or make it writeable before converting it to a tensor. This type of warning will be suppressed for the rest of this program. (Triggered internally at  /pytorch/torch/csrc/utils/tensor_numpy.cpp:141.)\n",
            "  return torch.from_numpy(parsed.astype(m[2], copy=False)).view(*s)\n"
          ],
          "name": "stderr"
        },
        {
          "output_type": "stream",
          "text": [
            "\n",
            "\n",
            "X_train.type()= torch.FloatTensor y_train.type()= torch.LongTensor\n",
            "batch_idx= 0 X_train.shape= torch.Size([100, 1, 28, 28]) y_train.shape= torch.Size([100]) y_train= tensor([6, 2, 8, 1, 4, 7, 2, 1, 8, 6, 3, 0, 2, 9, 7, 7, 0, 3, 7, 4, 7, 7, 4, 5,\n",
            "        5, 9, 8, 9, 6, 6, 2, 3, 1, 6, 7, 6, 7, 9, 1, 1, 1, 9, 1, 5, 6, 8, 8, 3,\n",
            "        3, 3, 8, 7, 0, 8, 7, 3, 3, 8, 3, 8, 2, 1, 8, 6, 8, 8, 6, 9, 1, 5, 1, 7,\n",
            "        7, 8, 5, 4, 7, 7, 3, 4, 6, 6, 7, 4, 4, 6, 6, 3, 7, 8, 4, 8, 2, 8, 6, 5,\n",
            "        8, 7, 5, 4])\n",
            "\n",
            "\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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bc25CsCVV16Z6P/ud7+L2hs2bOj2cuJ5OHny5LKP3bhxY9SeN29eYuzIIws/Ta0tVxGRLKi4iohkwMrtrtPosjhE8Ljjjkv0//CHP5R8bHy3k0p873vfi9rp3UzKKbe++FQDwP333x+1R48enRj705/+FLVPPPHEbq+/C51e2116plEPf91nn32i9sKFC8s+Nl6brr322sTYTTfdFLXT0xLxM2/lpNPc1pariEgGVFxFRDKg4ioikgHtilWlLM6EFV9mevnvvvtuon/KKad0a5np57344otR+4gjjqg0RJFuGTgweXra+AUK05555plEPz7PunTp0sRYnlcU6CltuYqIZEDFVUQkAyquIiIZ0JxrlcrtJ3zFFVdE7WuuuaZHy0wv//vf/36iP2fOnG4vt9Q60qcqFKlEW1tboj906NConT5F5he+8IWSy1m9enWiX24f8kagLVcRkQyouIqIZEDTAhnaY489onbv3r0TY+XOkjV+fOmrJ69du7b6wESqFD9z2sUXX5wYix/imhY/NHXu3LmJsU2bNtUoumLQlquISAZUXEVEMqDiKiKSAc25Vmjx4sWJ/pIlS6J2+sqwY8eOjdovv/xyYuz666+P2qeeempibNSoUVF70aJFibH0ckTycO655yb65513XtQuN8eaFt/d6phjjkmMHXRQc52RUluuIiIZUHEVEcmApgUq9MYbbyT6d955Z9ROny097qc//WnZftwWW2z+n1fJWbfSR2/Fj8JK794Vn3qIrw9g4sSJ3V6ntIb9998/0T/44IN7tJyHH3645Nj8+fN7tMyi0pariEgGVFxFRDJQuOJqZkPM7DEzW2xmi8xsQnj/jmb2iJktDX/2r3esIpVQbreWwl391cwGAYPcfYGZbQ88B5wMnAWsd/frzGwS0N/dL+tiWZm/uPhhrRdddFFirNwcbDnxedb076e9vT3R//DDD6P2iBEjEmPd/d2++eabif6hhx5acn1VaPmrvzZabsd98YtfTPRnz54dtffee+9uL2flypVRO567AC+88EKiP2XKlJLLmTdvXtSuw9Ve0xrj6q/u3u7uC8L2+8ASYDAwBpgRPmwGQVKKNAzldmsp9N4CZjYcOACYBwx0947NqFXAwBLPGQ+UPvOJSAEot5tf4aYFOpjZdsATwLXufr+Zvevu/WLj77h72bmpvD86pXeb+uY3vxm14yfOBthvv/2i9rbbbltyOZX8ftLrL/fct99+O2qnL1CY0VFgLT8t0KERczvtzDPPjNozZ85MjHV398FK8jXtgQceiNq33HJLYmyXXXaJ2vFdJSGzE8M3xrQAgJn1Bu4D7nT3+8O7V4dzVh1zV8W//KNIinK7dRSuuFrw7+x2YIm7T44NPQR0XE+iDXgw79hEqqHcbi1FnHM9FBgLvGhmz4f3XQ5cB9xjZuOAN4DT6hSfSE8pt1tIYedca6He81LlnHTSSVE7fbjp6NGjo3Ylv5/0ckaOHFnysbfddlvUXrhwYbfXUQXNudZQkXI7fZHMww47rE6RfF76wqC//e1vo3YNv1tonDlXEZFGp+IqIpIBTQtIXjQtUENFyu34hTgB2traovbpp5+eGEsfRVgLy5YtS/TXr18ftV999dXE2IQJE6L2O++8U6sQNC0gIpIXFVcRkQyouIqIZEBzrpIXzbnWUKPk9u67757of+Mb3+j2c7fffvuSz3vwwc3HWTz66KOJseXLl1cQYU1ozlVEJC8qriIiGdC0gORF0wI1pNwuFE0LiIjkRcVVRCQDKq4iIhlQcRURyYCKq4hIBlRcRUQyoOIqIpIBFVcRkQyouIqIZEDFVUQkA0W8+mstrSW4muZOYbsIihQL5BfPsBzW0UqU2+XlGUunud3U5xboYGbzi3Jce5FigeLFI5Up0u9PsSRpWkBEJAMqriIiGWiV4jq13gHEFCkWKF48Upki/f4US0xLzLmKiOStVbZcRURypeIqIpKBpi6uZnasmb1iZsvMbFId1j/NzNaY2Uux+3Y0s0fMbGn4s39OsQwxs8fMbLGZLTKzCfWMR6qj3E7EUsjcbtriama9gCnAccAo4AwzG5VzGNOBY1P3TQJmu/uewOywn4dPgYvdfRTwVeC74ftRr3ikh5Tbn1PI3G7a4gocAixz97+6+ybgLmBMngG4+xxgferuMcCMsD0DODmnWNrdfUHYfh9YAgyuVzxSFeV2MpZC5nYzF9fBwIpY/63wvnob6O7tYXsVMDDvAMxsOHAAMK8I8UjFlNslFCm3m7m4Fp4H+8Hlui+cmW0H3AdMdPcN9Y5HmpNyu7mL60pgSKy/W3hfva02s0EA4c81ea3YzHoTJN+d7n5/veORHlNupxQxt5u5uD4L7GlmXzKzPsDpwEN1jgmCGNrCdhvwYB4rNTMDbgeWuPvkescjVVFuxxQ2t929aW/A8cCrwGvAj+qw/llAO/AJwbzYOGAAwTeXS4FHgR1ziuUwgo9FC4Hnw9vx9YpHt6p/n8rtzbEUMrd1+KuISAaaeVpARKRuVFxFRDLQcMW13of9iWRBed18GmrONTzs71XgaIJJ9GeBM9x9cYnHN86La35r3X3negdRRJXmdfgc5XZxdJrbjbblWvfD/qTH3qh3AAWmvG5sneZ2oxXXLg/7M7PxZjbfzObnGplIz3XrcFbldmNpuktru/tUwks86KOTNBPldmNptC3Xoh72J1IN5XUTarTiWtTD/kSqobxuQg01LeDun5rZhcDDQC9gmrsvqnNYIlVRXjenhtoVq1KalyqU59z9oHoH0SyU24XSaW432rSAiEhDUHEVEcmAiquISAZUXEVEMqDiKiKSARVXEZEMNNR+riJSfE899VTUHjlyZGLs6KOPjtoLFizILaZ60JariEgGVFxFRDKg4ioikgHNuRbcVVddleiPHj060T/88MOj9tVXX132uSJ5iB9S37dv38TYI488ErUHDBiQW0z1oC1XEZEMqLiKiGRAZ8Wqk/jH+SuvvLLkWDUef/zxqH3EEUfUZJlV0FmxaqjIuX366adH7d/85jclH7fllk0zK6mzYomI5EXFVUQkAyquIiIZ0JxrTtLzqI899liu64/Pv0Jd5mA151pDRcrttPguVr///e8TY1/72tei9rhx4xJjM2bMyDaw7GjOVUQkLyquIiIZaJp9IYoo/tG/VrtXpcU/7pdbR3os3k9PGYhUY926dVH7b3/7W8nH7bvvvnmEUzfachURyYCKq4hIBlRcRUQyoDnXgqvmTFfldrPTnKvkYe7cuYn+qaeeGrXNLO9wcqUtVxGRDBSyuJrZNDNbY2Yvxe7b0cweMbOl4c/+9YxRpFLK69ZSyCO0zOzrwEZgprvvE973c2C9u19nZpOA/u5+WRfLqeuLi3+ET5/5Ki79sTw+FVDJR/aeHgWW08ezlj9Cq1Z5HT6veH+4nRgyZEii//rrr0ftG264ITF2ySWX5BJTBhrnCC13nwOsT909Bug4Pm4GcHKuQYlUSXndWhrpC62B7t4etlcBAzt7kJmNB8bnFpVIdbqV16DcbjSNVFwj7u6lPha5+1RgKjTORycRKJ/X4bhyu4E0UnFdbWaD3L3dzAYBa+odUFe6O+f6xBNPJPo93TUq7zNtSU00XF7Xyq677pro9+nTJ9HftGlTnuHUXCHnXEt4CGgL223Ag3WMRaRWlNdNqpDF1cxmAU8DI83sLTMbB1wHHG1mS4Gjwr5Iw1Bet5ZCTgu4+xklho7MNZAaSp+cOv4RPj1lMHr06JLPSx+hVW66Ia4AJ8tuec2Y19XYZZddEn1NC4iISJdUXEVEMqDiKiKSgUIe/lorRd4XMI/3PX4YbSVn08pIyx/+WktFzu24coe/pg+7Hjp0aKK/cuXK7AKrrcY5/FVEpNGpuIqIZKCQu2I1o6wuUBiX3r1KJ8GWoolPBWyxRXNv2zX3qxMRqRMVVxGRDKi4iohkQHOuGYof4prVnGtPr1ogUg/xXRA/++yzxNiPf/zjRP+CCy7IJaasaMtVRCQDKq4iIhlQcRURyYDmXGsofSWA7s6zpudK01cmiEufYjDeL8AhriI91rdv33qHUFPachURyYCKq4hIBjQtUKX4R/FKdrfq6Rmr4lcpSK8zPS2hqw2I1I+2XEVEMqDiKiKSARVXEZEMaM61Sj29+mpPd5tK76YVn3PN47SGItI92nIVEcmAiquISAY0LVCl+Mf9ch/Lyx111dP1QflpifjUg47eknpYsWJFon/jjTdG7Ysuuigxdtppp5V87F/+8pcMosuWtlxFRDJQuOJqZkPM7DEzW2xmi8xsQnj/jmb2iJktDX/2r3esIpVQbreWwhVX4FPgYncfBXwV+K6ZjQImAbPdfU9gdtgXaSTK7RZSuDlXd28H2sP2+2a2BBgMjAEODx82A3gcuKwOISbED2MtN+eanhvt6RyorjbQuBott7PwwgsvRO30lQjiVynorN9oCldc48xsOHAAMA8YGCYnwCpgYInnjAfG5xGfSE8pt5tfEacFADCz7YD7gInuviE+5sG/tE7/rbn7VHc/yN0PyiFMkYopt1tDIbdczaw3QfLd6e73h3evNrNB7t5uZoOANfWLcLP4x/T0R/Zy0wTxM1hVcvYq7VLV2Bopt7Mwc+bMqH3HHXfUMZLsFW7L1cwMuB1Y4u6TY0MPAW1huw14MO/YRKqh3G4tRdxyPRQYC7xoZs+H910OXAfcY2bjgDeA00o8X6SolNstpHDF1d2fBKzE8JF5xiJSS8rt1lK44trI0nOn5XYlic/HZrXLSfqqBSJFEp9/BRg7dmydIslG4eZcRUSagYqriEgGNC2Qofg0QfoIrSxObJ3eFSx+9JhI0SxcuLDeIWRKW64iIhlQcRURyYCKq4hIBqzRzzxTjpkV9sXFD2NN7zJV7qoF6XnVBjpL1nM6Jr52ipzbLajT3NaWq4hIBlRcRUQyoGkByYumBWpIuV0omhYQEcmLiquISAZUXEVEMqDiKiKSARVXEZEMqLiKiGRAxVVEJAMqriIiGVBxFRHJgIqriEgGmv1KBGsJLlW8U9gugiLFAvnFMyyHdbQS5XZ5ecbSaW439bkFOpjZ/KIc116kWKB48UhlivT7UyxJmhYQEcmAiquISAZapbhOrXcAMUWKBYoXj1SmSL8/xRLTEnOuIiJ5a5UtVxGRXKm4iohkoKmLq5kda2avmNkyM5tUh/VPM7M1ZvZS7L4dzewRM1sa/uyfUyxDzOwxM1tsZovMbEI945HqKLcTsRQyt5u2uJpZL2AKcBwwCjjDzEblHMZ04NjUfZOA2e6+JzA77OfhU+Bidx8FfBX4bvh+1Cse6SHl9ucUMrebtrgChwDL3P2v7r4JuAsYk2cA7j4HWJ+6ewwwI2zPAE7OKZZ2d18Qtt8HlgCD6xWPVEW5nYylkLndzMV1MLAi1n8rvK/eBrp7e9heBQzMOwAzGw4cAMwrQjxSMeV2CUXK7WYuroXnwX5wue4LZ2bbAfcBE919Q73jkeak3G7u4roSGBLr7xbeV2+rzWwQQPhzTV4rNrPeBMl3p7vfX+94pMeU2ylFzO1mLq7PAnua2ZfMrA9wOvBQnWOCIIa2sN0GPJjHSs3MgNuBJe4+ud7xSFWU2zGFzW13b9obcDzwKvAa8KM6rH8W0A58QjAvNg4YQPDN5VLgUWDHnGI5jOBj0ULg+fB2fL3i0a3q36dye3MshcxtHf4qIpKBZp4WEBGpGxVXEZEMqLiKiGRAxVVEJAMqriIiGVBxFRHJgIqriEgG/j+y/9bPlM824wAAAABJRU5ErkJggg==\n",
            "text/plain": [
              "<Figure size 432x288 with 4 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        },
        {
          "output_type": "stream",
          "text": [
            "X_train.shape= torch.Size([100, 784])\n",
            "X_test.shape= torch.Size([10, 784])\n",
            "Generate Model:\n",
            "0 2.362582206726074\n",
            "2 1.2706376314163208\n",
            "4 0.6602278351783752\n",
            "6 0.35273993015289307\n",
            "8 0.1899886280298233\n",
            "Duration of optimization: 0.3385353088378906\n",
            "Loss on the test set: tensor(2.7035, grad_fn=<NllLossBackward>)\n",
            "Wrote to mnistexample_pytorch_weights.torch\n",
            "sample.shape= torch.Size([784])\n",
            "Test Ypred= tensor([-1.0807, -0.4439, -0.7421, -0.2596, -1.1628,  0.3973,  1.6357, -0.6643,\n",
            "         0.2844, -1.3932], grad_fn=<AddBackward0>)\n",
            "prediction= tensor(6)\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ZAP7LSZyEVus"
      },
      "source": [
        "## Unknown Test Image"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "hide_input": true,
        "id": "LI_-8ZXgEVus",
        "outputId": "73a021d5-b7fb-49d3-8e4c-3eb82e78005b",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 336
        }
      },
      "source": [
        "%%html\n",
        "<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/rV7KpLe1nRk?rel=0\" frameborder=\"0\" allow=\"accelerometer; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>"
      ],
      "execution_count": 10,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/rV7KpLe1nRk?rel=0\" frameborder=\"0\" allow=\"accelerometer; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ABYaniAbEVuv"
      },
      "source": [
        "To test this case of an unknown image, we generate a 28x28 picture containing just random numbers between 0 and 1 (or 0 and 255 in a jpeg image)."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "cqZ9RKoSEVuv"
      },
      "source": [
        "import cv2\n",
        "import numpy as np\n",
        "rpic=np.random.rand(28,28)*255 #range for 8 bit unsigned integer\n",
        "cv2.imwrite(\"./images/randpic.jpg\", rpic);"
      ],
      "execution_count": 13,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vW5I3taFEVux"
      },
      "source": [
        "We extend our main program section such that it inlcudes reading our random jpeg image for testing after it took an image from the MNIST test set:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "WLk9bmFKEVu0",
        "outputId": "acfbbc00-bd86-4bd9-ac9c-dcc906a81c7d",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 814
        }
      },
      "source": [
        "#\"Inference\", predict an example digit test image:\n",
        "for pic in range(2):\n",
        "    print(\"Picture \", pic)\n",
        "    if pic==0: #take image from test set:\n",
        "        X_testorig=X_testunflat[1,0]\n",
        "        sample=X_test[1,:]\n",
        "    if pic==1: #read externa random test image, size 28x28 pixel:\n",
        "        from PIL import Image\n",
        "        image = Image.open('./images/randpic.jpg')\n",
        "        import torchvision.transforms.functional as TF\n",
        "        X_testorig = TF.to_tensor(image)\n",
        "        X_testorig = X_testorig[0,:,:]\n",
        "        sample=X_testorig.view(28*28)\n",
        "        \n",
        "    plt.imshow(X_testorig, cmap=plt.get_cmap('gray'))\n",
        "    plt.title(\"A Digit Image to Regognize as a Test (predicted digit in the shell)\")\n",
        "\n",
        "    print(\"sample.shape=\", sample.shape)\n",
        "    Ypred=model(sample)\n",
        "    sm = torch.nn.Softmax(dim=0)\n",
        "    print(\"Test Ypred=\", Ypred)\n",
        "    probabilities = sm(Ypred.detach())\n",
        "    print(\"Probabilities:\",probabilities)\n",
        "    prediction=torch.argmax(probabilities) #use argmax as the class with the largest output\n",
        "    print(\"prediction=\", prediction)\n",
        "    if probabilities[prediction] <0.8 : #not confident\n",
        "        print(\"Probably not a digit\")\n",
        "    plt.show()"
      ],
      "execution_count": 12,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Picture  0\n",
            "sample.shape= torch.Size([784])\n",
            "Test Ypred= tensor([-1.0807, -0.4439, -0.7421, -0.2596, -1.1628,  0.3973,  1.6357, -0.6643,\n",
            "         0.2844, -1.3932], grad_fn=<AddBackward0>)\n",
            "Probabilities: tensor([0.0302, 0.0570, 0.0423, 0.0685, 0.0278, 0.1322, 0.4561, 0.0457, 0.1181,\n",
            "        0.0221])\n",
            "prediction= tensor(6)\n",
            "Probably not a digit\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZYAAAEICAYAAAB8lNKlAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAdTElEQVR4nO3df/xUZZ338dc7kEygRC1FUknT0iTJSG2XVbsrM6zQ2jBzEyulQtvWR7vm7b1t3KVlP+zHfdsPMV2kDMU1f7W1WW5kZWrokr9/sIoJIYSmopklfPaP6/raYZw535kvFzMDvJ+PBw9mzuecM5+5zjXnc851zsxXEYGZmVkpz+l1AmZmtmlxYTEzs6JcWMzMrCgXFjMzK8qFxczMinJhMTOzonpSWCSdKumbpee1/ibpB5Km9zqPjZGkeZIO79JrHSvp55Xnj0vatQuvu0DScW3Oe7CkpZXnt0k6uM1l2553KPMPsq518t5QJIWkl67vspLmSDotP36lpGvbWUfbhSVv9N9Lem4b8/1R0mpJj0m6UdIp1eUi4tMR0VYHqs4raXx+08NrXn+WpG+3+756RdISSW9Yj+VD0hP5Q79M0hclDSuZY2kR8eaIOL/XeayPvJN5PP9bk/v6wPNTh7C+Zz64NfO8EtgHuHyoea+PiBgVEffWzdPOZ3NDiohXRMSCTudtZ3/Rybobrc8Ovt9ExM3AI5LeOti8bRUWSeOBvwECeFsbi5wYEaOBscBHgXcB35ekdl7P2rZPRIwCDgKOBN7X43w2eXknMyq3+89IfX1U/vfpDfSyHwAuiCF8m1mJh7ytlAtI/bFWux3uGOA6YA7Q9lBGRDyRK/3bgNcCh8GzjxIkHSPpfkkPSfp49Wi+Yd5r8v+P5CPE1w6WQz5imCnpnnwW9SlJu0m6Np9RzZc0Is87RtL3JP0un519T9KLK+t6iaRr8np+LOmrDe/jgLzeRyT9utXps6RvATsDV+b3cXKe/rZ8RPxIPvPbs812Xgz8AphYeY23SFqU13VtPuodiO0r6b/y+7hY0kXVo2ZJx0taLOlhSVdI2rESO0TSXZIelfQ1ST9VHr5QHkKR9IXcfvdJenNl2QWVeX9dOdJ/PG+ngztpxzzvKZL+O7+X2yUdUYm9NOf3qKRVki6qWc/Fkh7M814j6RXttH3DOt4n6Y783n8oaZc8XZK+JGll7nO3SNpb0gzgaODk3AZXtlj1m4GfVl7nWEm/kHRWzvdOSa+vxBdIOl3SL4A/ALtKermkH+VtepekaZX5t83b+TFJNwC7Nbyv6tDI8ySdqfR5fTRv7+fR4rPZqk1y7I0590clnQW0PPDMrzsnr+d24DUN8eo+43mSzs/z3iHpZK07bLZE0hskHQqcChyZc/51i9du3B/NlzQ397nbJE1qsdxAmwz09SMrsY/m/rBc0nsr05+bPz+/kbRC0jdy+zZb/2D9+w1K+71HlPZVqizbcrsMYgHweg0yckVEDPoPWAzMBF4N/BnYvmbeBcBxTaZfA3w2P54FfDs/3gt4HJgMjAC+kF/jDU3mHU86axpe8/rPzJ+fB2kI4fnAK4CngKuBXYEXALcD0/O82wLvALYCRgMXA5dV1vXLnN+InO9jldzGAQ8BU0gF+435+Qtb5Llk4D3m53sAT+TltgBOzu0+osXyAbw0P345sBw4KT9/FbAS2B8YRjoYWAI8N+d+P/CR/DpvB/4EnJaX/V/AKmDfPP//B67Jse3ye347MDyv488D2xs4Nj8/Pr/uh4DfAhqkb8wA7szbqNN2fCewY573yNyGY3NsHvB/cmxLYHJNv3lf3ubPBb4MLGrjc/HM+wGm5u21Z26bfwauzbE3ATcCW5N2nntWcpwz0PYtXmNk3tYvrEw7FngaOClvwyOBR4FtKnn9htTfh5P6+QPAe/PzV+VtvFee/0Jgfn6tvYFlwM9b9LWv5vWPy9v4r3KbjafhszlIm2wHrAb+Nr+Hk/J7elb/yPOfQTpD3AbYCbgVWNrs85Tn/SkwBngxcHPNvLOo7C8G+6zm+f9I6p/DgM8A19Us+0zb5ecH5/f5yfy+p5CK/5gc/xJwRX6fo4Ergc+0WHfL/p1f93ukPrcz8Dvg0MG2S5PtPYeG/knaB7yyts3a+PBMJu0stsvP7yTvwAb7sDVMvxA4p3FjAv8CzKvMtxVpR1eysPx15fmNwMcqz88EvtxiXROB3+fHO+cOsVUl/u1Kbh8DvtWw/A/JRauus+bnHwfmV54/h/QBP7imwz5G2pFG7mTPzbGvA59qmP8u0pDZgXm9qsR+zl8Ky7nA5yqxUXn7jyeduf6yEhNph1UtLIsbtmUAO7TqG7l/rQT2GEo7NmmXRcDU/HguMBt4cTvLVtaxdc77BYPM98z7AX4AvL9h+/0B2IVUrO8GDgCe07COOdQXlnE5ly0r046lUrDztBuA91Ty+mQldiTws4b1ng18grRz/DPw8krs0zQpLPk9PUkagm3MczzPLix1bXIMlR1y7ktLG/tHJX4veceYn8+gdbG4F3hTJXZczbyz6Lyw/LgS2wt4smbZZoXlyYZ2Wpn7hkif590qsdcC97VYd8v+nV+3WmjmA6cMtl0ac27WP0n7jwPr2qydobDpwFURsSo//w4dDIdVjAMebjJ9R9LOCYCI+APpCLWkFZXHTzZ5PgpA0laSzs6n+Y+RzrK2VrooviPwcM5vwAOVx7sA78ynnY9IeoS00xzbZo47ks4kAIiItXn942qW2TfnfiTp7GRkJZePNuSyU36NHYFlkXtIk/fRmMfjpO0xjmdvqyDtDKoerMQH2mpUs+Ql7UTq8NMj4u5K7m23o9Iw6qLKvHuTjoYhnfUJuCEPWTS9BiVpmKQzlIbUHiPtSKispx27AF+p5PFwfu1xEfGfwFmko/2VkmZLen6b630k/z+6YXrjNryftH0GNPbN/Rva9GhgB+CFpKPW6vz309x2pCPj/24z95ZtQvO+9EDTtSQ70l6OzeatW+9QPFh5/AdgS3V208JDEfF0wzpGkbbFVsCNlTb7jzy9mcH6d2OeA5/Duu3SjtH8pV82VVtY8tjeNOAgpfHnB0mnrPtI2qfNJAZ2IK8mnco2Wk46Xa2+5rYtVhUtppfyUeBlwP4R8XzS0T2kRl8ObCNpq8r8O1UeP0A60t668m9kRJzR4rUa38tvSRs8vWAaD92JdHTQUiTzScN0/1LJ5fSGXLaKiHn5fYyrjrc2vI/GPEaStscynr2tVH3eibydLyOdLf6gEmq7HfO48DnAicC2EbE1aYhEABHxYEQcHxE7ki44fk3N79B5N2l44A2kYaPxAy/RwVt6APhAQ97Pi4hrcy7/LyJeTTrC3QP4p7xcbZ+OiCdIO/I9GkKN23Bn0rZ7ZtGG3H7akNuoiPgQaYjkadbtAzu3SGcVaRhotyaxZu+jrk2WV1+z0t9bWU57OQ7MW+2Xdevd0PuUTqwiHei+otJeL4h0o8izdNC/G9X21TqSxpGG0++qm2+wM5bDgTWkD8PE/G9PUoE4po0ktpJ0EOkaxw3A95vM9m/AWyX9ldJF9Fm0/kD/DlhLuj6yIYwmbdhHJG1DGioAICLuBxYCsySNULo4Wb3t7tuk9/GmfAS8pdI96612vCtY933MBw6T9HpJW5CK3FNAW/eNk8aVj5e0A2ln+0FJ+ysZKekwSaNJBWgNcKKk4ZKmAvtV1jMPeK+kifkC3aeB6yNiCfDvwARJh+cjtBNIR71DcR5wZ0R8rmF6J+04cP3hdwD5IujeA0FJ76ws9/s879om6xlNauuHSEeMQ7m76xvA/1a+6C/pBZLemR+/Jm+LLUhDHX+s5NHYD5r5PmkYs+pFwN9L2iK/zp40/3xBGmvfQ9J78vxb5Jz2jIg1wHdJ/XorSXvRYkQin0WfB3xR0o55+7w295Nmn82WbULqS6+Q9Pbcl/6e+r40P69rTN6mH25z3nGkA49WVgDjteHunGtn+wLPtO85wJckvQjSjlzSm5rN30H/blS3XQZzEPCfEfFU3UyDNeZ04F8j4je5Oj4YEQ+STuuPrjn9O0vSalKjfhm4hDQ++qw3HRG3kTrJhaQjjcdJY47PSjwPrZwO/CKfxh0wSP6d+jLwPNKRw3Wk09Cqo0ljng8BpwEXDeQZEQ+QjnpPJX3IHiAdlbZq488A/5zfxz9GxF3A35Eulq8iFa23RsSf2kk8Im4hDd39U0QsJF1AP4vU4RaTxuXJ63s78H7S6ezfkXY8A+/jx6TrPZeQtsdupNvFycOh7wQ+l9tgL1Kxre1kLbwLOELr3hn2N520Y0TcTrpG9ktSX5tAujtuwGuA6yU9Trog+pFo/n2MuaShlWWkmzmu6/TNRMSlwGeBC/Nw2q2ku7kg3ZRwDmlb3E9qu8/n2LnAXrkfXNZi9bNJn7fqAdf1wO6kvnI68LcR0XQIOSJWA4eQ2vy3pCGSz5IuukPa8Y7K0+cA/1rzVv8RuAX4FWkI5bOk60bP+mzWtUmlL52R22N31t12jf4vqe3uA64CvlUz7ydJQ7T3AT8mHby26qMX5/8fknRTzTqHahZwfm6TaYPNTLrGuBi4LrfZj0mjKM2027/XMUhfHczRpMJUa+Bunb4haRRph7d7RNzX63zqKN3ed2dEfGLQmfuYpOuBb0RE3Q6l2XLPIX2Aj46In2yQ5AwASd8h3dxxmaRjSRe5J/c4rY2CpA8B74qIxrM+64DSVxbOjohBv+bRF1+ckvTWfBo+knQ77y385QJq38jDB7tJeo7SPfBTSdcJNiqSDpK0Qx4Kmw68kmefnbVa9k2Sts7DH6eShi07PsK3zkTEuyNio+trvSBprKS/zp/Tl5GGlS/tdV4bu4i4uZ2iAulukH4wlXRqK9LQyrui306lkh1I49Hbko7UPxQR/9XblIbkZfzlewv3koZRlre57GtJdwaOIA0bHR4RT26QLM2GZgTpduqXkEY/LgS+1tOMNjN9NxRmZmYbt74YCjMzs01HvwyFbZYk+XTRbAOLCP/4bZf5jKUgSYcq/cDfYkmn9DofM7Ne8DWWQpR+9uVu0o8mLiXd539U/q5Fq2Xc+GYbmM9Yus9nLOXsR/oBxnvzlxAvJN3tZma2WXFhKWcc6/7Y3VKa/KibpBmSFkpa2LXMzMy6yBfvuywiZpN+osNDYWa2SfIZSznLWPdXVF/MIL9MbGa2KXJhKedXwO5Kf754BOkH/67ocU5mZl3nobBCIuJpSSeS/trhMOC8/MvNZmabFd9u3EO+xmK24fl24+7zUJiZmRXlwmJmZkW5sJiZWVEuLGZmVpQLi5mZFeXCYmZmRbmwmJlZUS4sZmZWlAuLmZkV5cJiZmZFubCYmVlRLixmZlaUC4uZmRXlwmJmZkW5sJiZWVEuLGZmVpQLi5mZFeXCYmZmRbmwmJlZUS4sZmZWlAuLmZkVNbzXCZhZsvfee9fG586dWxtfvHhxbXzmzJktY6tWrapd1qwTPmMxM7OiXFjMzKwoFxYzMyvKhcXMzIpyYTEzs6JcWMzMrCgXFjMzK8rfYzHrokMPPbRl7OKLL65dduTIkbXxiRMn1sZvvvnmlrHTTjutdlmzTriwFCRpCbAaWAM8HRGTepuRmVn3ubCU97qI8NeYzWyz5WssZmZWlAtLWQFcJelGSTOazSBphqSFkhZ2OTczs67wUFhZkyNimaQXAT+SdGdEXFOdISJmA7MBJEUvkjQz25B8xlJQRCzL/68ELgX2621GZmbd58JSiKSRkkYPPAYOAW7tbVZmZt3nobBytgculQSpXb8TEf/R25Ss284888za+HHHHdcytuWWW9Yue8IJJ9TGp0yZUhufMGFCbdysFBeWQiLiXmCfXudhZtZrHgozM7OiXFjMzKwoFxYzMyvKhcXMzIpyYTEzs6J8V5hZB44//vja+IwZTX/J5xl1txQfe+yxtctecMEFQ143wAEHHFAbNyvFZyxmZlaUC4uZmRXlwmJmZkW5sJiZWVEuLGZmVpQLi5mZFeXCYmZmRfl7LGYVkyZNqo2fffbZtfGnnnqqNv7+97+/ZWyw76mYbSx8xmJmZkW5sJiZWVEuLGZmVpQLi5mZFeXCYmZmRbmwmJlZUS4sZmZWlL/HYpuV0aNH18bPOuus9Vr/zJkza+Nz584d8rqHD6//uB5xxBG18eXLlw/5tc064TMWMzMryoXFzMyKcmExM7OiXFjMzKwoFxYzMyvKhcXMzIpyYTEzs6L8PRbbrOyzzz618f322682vnLlytr4FVdc0XFO7TrssMNq45MnT66Nf/7zny+ZjllLPmPpkKTzJK2UdGtl2jaSfiTpnvz/mF7maGbWSy4snZsDHNow7RTg6ojYHbg6Pzcz2yy5sHQoIq4BHm6YPBU4Pz8+Hzi8q0mZmfURX2MpY/uIGPghpgeB7VvNKGkGMKMrWZmZ9YALS2EREZKiJj4bmA1QN5+Z2cbKQ2FlrJA0FiD/X3/rkJnZJsyFpYwrgOn58XTg8h7mYmbWU4rwaEwnJM0DDga2A1YAnwAuA+YDOwP3A9MiovECf7N1ufG7bLDvmbzlLW+pjU+dOrU2fuWVV3acU7sG+1sukyZNqo1PmDChZWzNmjVDymljEBHqdQ6bG19j6VBEHNUi9PquJmJm1qc8FGZmZkW5sJiZWVEuLGZmVpQLi5mZFeXCYmZmRfmuMNvkTJw4sWXskEMOqV32iSeeqI1vyNuJB7vV+aijWt2QmHzlK1+pjW/KtxRbf/EZi5mZFeXCYmZmRbmwmJlZUS4sZmZWlAuLmZkV5cJiZmZFubCYmVlR/h6LbXJOOumklrERI0bULnv66aeXTqdt73nPe2rjjz76aG18/vz5JdMxGzKfsZiZWVEuLGZmVpQLi5mZFeXCYmZmRbmwmJlZUS4sZmZWlAuLmZkVpYjodQ6bLUlu/CGYNm1abfyiiy5qGbvhhhtql91///2HlFO7jjnmmJaxOXPm1C579NFH18bnzZs3lJQ2eRGhXuewufEZi5mZFeXCYmZmRbmwmJlZUS4sZmZWlAuLmZkV5cJiZmZFubCYmVlR/h5LD/l7LM0NGzasNn7ZZZfVxidMmNAyNnny5Nplly5dWhsfzIEHHlgbv+qqq1rGFi1aVLvs6173utr4k08+WRvfXPl7LN3nM5YOSTpP0kpJt1amzZK0TNKi/G9KL3M0M+slF5bOzQEObTL9SxExMf/7fpdzMjPrGy4sHYqIa4CHe52HmVm/cmEp50RJN+ehsjGtZpI0Q9JCSQu7mZyZWbe4sJTxdWA3YCKwHDiz1YwRMTsiJkXEpG4lZ2bWTS4sBUTEiohYExFrgXOA/Xqdk5lZr7iwFCBpbOXpEcCtreY1M9vUDe91AhsbSfOAg4HtJC0FPgEcLGkiEMAS4AM9S3AT8O53v7s2fthhh9XG6/6uyfp+T2WXXXapjV966aW18bVr17aMzZw5s3ZZf0/FNhYuLB2KiKOaTD6364mYmfUpD4WZmVlRLixmZlaUC4uZmRXlwmJmZkW5sJiZWVG+K8z6zjve8Y7a+LJly2rjZ5xxRsl01rFgwYLa+JgxLX/NB4Cjjmp2U2Fy0003DSUls77jMxYzMyvKhcXMzIpyYTEzs6JcWMzMrCgXFjMzK8qFxczMinJhMTOzovw9Fuu6Aw88sDY+ZcqU2vhgP01/9913t4ztuuuutctefvnltfHBfjb/q1/9am38kksuqY2bbQp8xmJmZkW5sJiZWVEuLGZmVpQLi5mZFeXCYmZmRbmwmJlZUS4sZmZWlL/HYl03derU2vjw4fXd8sorr6yNT548uWVs/vz5tcvusMMOtfHbbrutNv7xj3+8Nv7000/Xxs02BT5jMTOzolxYzMysKBcWMzMryoXFzMyKcmExM7OiXFjMzKwoFxYzMyvK32PpkKSdgLnA9kAAsyPiK5K2AS4CxgNLgGkR8fte5bkp+/CHP1wb33fffVvGhg0bVrvsueeeWxs//vjja+Nm5jOWoXga+GhE7AUcAJwgaS/gFODqiNgduDo/NzPb7LiwdCgilkfETfnxauAOYBwwFTg/z3Y+cHhvMjQz6y0XlvUgaTzwKuB6YPuIWJ5DD5KGyszMNju+xjJEkkYBlwD/EBGPSXomFhEhKVosNwOY0Z0szcy6z2csQyBpC1JRuSAivpsnr5A0NsfHAiubLRsRsyNiUkRM6k62Zmbd5cLSIaVTk3OBOyLii5XQFcD0/Hg6cHm3czMz6weKaDpiYy1Imgz8DLgFWJsnn0q6zjIf2Bm4n3S78cODrGuTbPwxY8bUxu+5557a+DbbbLNer7969eqWsW9+85u1y5588sm18TVr1gwpJ+udiNDgc1lJvsbSoYj4OdCqo76+m7mYmfUjD4WZmVlRLixmZlaUC4uZmRXlwmJmZkW5sJiZWVEuLGZmVpRvN7biPvjBD9bGR40aVRtfvHhxbfyiiy6qjS9YsKBl7Oqrr65d1szWn89YzMysKBcWMzMryoXFzMyKcmExM7OiXFjMzKwoFxYzMyvKhcXMzIry32PpoU3177EM9j2T++67rzZ+yimnlEzHNnP+eyzd5zMWMzMryoXFzMyKcmExM7OiXFjMzKwoFxYzMyvKhcXMzIpyYTEzs6L8PZYe2lS/x2LWT/w9lu7zGYuZmRXlwmJmZkW5sJiZWVEuLGZmVpQLi5mZFeXCYmZmRbmwmJlZUS4sHZK0k6SfSLpd0m2SPpKnz5K0TNKi/G9Kr3M1M+sFf0GyQ5LGAmMj4iZJo4EbgcOBacDjEfGFDtblxjfbwPwFye4b3usENjYRsRxYnh+vlnQHMK63WZmZ9Q8Pha0HSeOBVwHX50knSrpZ0nmSxrRYZoakhZIWdilNM7Ou8lDYEEkaBfwUOD0ivitpe2AVEMCnSMNl7xtkHW58sw3MQ2Hd58IyBJK2AL4H/DAivtgkPh74XkTsPch63PhmG5gLS/d5KKxDkgScC9xRLSr5ov6AI4Bbu52bmVk/8BlLhyRNBn4G3AKszZNPBY4CJpKGwpYAH8gX+uvW5cY328B8xtJ9Liw95MJituG5sHSfh8LMzKwoFxYzMyvKhcXMzIpyYTEzs6JcWMzMrCgXFjMzK8qFxczMinJhMTOzolxYzMysKBcWMzMryoXFzMyKcmExM7OiXFjMzKwoFxYzMytqeK8T2MytAu7Pj7fLz/uRcxsa5zY0JXPbpdB6rAP+eyx9QtLCiJjU6zyacW5D49yGpp9zs/Z4KMzMzIpyYTEzs6JcWPrH7F4nUMO5DY1zG5p+zs3a4GssZmZWlM9YzMysKBcWMzMryoWlD0g6VNJdkhZLOqXX+VRJWiLpFkmLJC3scS7nSVop6dbKtG0k/UjSPfn/MX2U2yxJy3LbLZI0pQd57STpJ5Jul3SbpI/k6T1vt5rcet5utn58jaXHJA0D7gbeCCwFfgUcFRG39zSxTNISYFJE9PzLdJIOBB4H5kbE3nna54CHI+KMXJTHRMTH+iS3WcDjEfGFbudTyWssMDYibpI0GrgROBw4lh63W01u0+hxu9n68RlL7+0HLI6IeyPiT8CFwNQe59SXIuIa4OGGyVOB8/Pj80k7pq5rkVvPRcTyiLgpP14N3AGMow/arSY328i5sPTeOOCByvOl9NeHK4CrJN0oaUavk2li+4hYnh8/CGzfy2SaOFHSzXmorCfDdAMkjQdeBVxPn7VbQ27QR+1mnXNhscFMjoh9gTcDJ+Qhn74UaVy3n8Z2vw7sBkwElgNn9ioRSaOAS4B/iIjHqrFet1uT3Pqm3WxoXFh6bxmwU+X5i/O0vhARy/L/K4FLSUN3/WRFHqsfGLNf2eN8nhERKyJiTUSsBc6hR20naQvSjvuCiPhuntwX7dYst35pNxs6F5be+xWwu6SXSBoBvAu4osc5ASBpZL6oiqSRwCHArfVLdd0VwPT8eDpweQ9zWcfAjjs7gh60nSQB5wJ3RMQXK6Get1ur3Pqh3Wz9+K6wPpBvp/wyMAw4LyJO73FKAEjalXSWAulPLHynl7lJmgccTPpZ9RXAJ4DLgPnAzqQ/QTAtIrp+Eb1FbgeThnMCWAJ8oHJdo1t5TQZ+BtwCrM2TTyVdy+hpu9XkdhQ9bjdbPy4sZmZWlIfCzMysKBcWMzMryoXFzMyKcmExM7OiXFjMzKwoFxYzMyvKhcXMzIr6HxCVKCnv2DdsAAAAAElFTkSuQmCC\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        },
        {
          "output_type": "stream",
          "text": [
            "Picture  1\n",
            "sample.shape= torch.Size([784])\n",
            "Test Ypred= tensor([ 0.0945, -0.3732,  0.5522, -0.0677, -0.7717, -0.5112, -0.2774, -0.6847,\n",
            "         0.4926, -0.2874], grad_fn=<AddBackward0>)\n",
            "Probabilities: tensor([0.1199, 0.0751, 0.1894, 0.1019, 0.0504, 0.0654, 0.0826, 0.0550, 0.1785,\n",
            "        0.0818])\n",
            "prediction= tensor(2)\n",
            "Probably not a digit\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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fTVPp8CjmLGwxEhV5yF8TQwiol8EDoUREVGsWFiIiChWLCxERBQrFhYiIooVCwsREcWKhYWIiGLF3Y1TqFSpUjjmmGOC+cSJE8321jETv/rVr8y2UaeujzoN+qxZs4LZU089ZbYdOXKkmfft29fM27VrZ+bW8SC33HKL2TY9Pd3Ma9eubeYPPPCAmVvX0LGuIwNEX59n3jx7T/dnn302mDVq1Mhs27BhQzMfNWqUmV9wwQVmbl2PxbqODAB06tQpmEUd80SFg1ssREQUKxYWIiKKFQsLERHFioWFiIhixcJCRESxYmEhIqJYiaqmug+/WFWqVNE2bdoE86FDh5rtBw0aFMxuv/12s23U7sTWKdYBYN++fcHs4osvNttmZWWZedOmTc38rrvuMvMnn3wymB08eNBsa+32CgCjR48280qVKhU4X79+vdn2j3/8o5k/+OCDZj516tRgdv7555ttrXkKANnZ2Wbes2dPM+/atWswi9qVuWLFisFs+fLlyMrKEvMBKHbcYiEiolixsBARUaxYWIiIKFYsLEREFCsWFiIiihULCxERxYqFhYiIYsXT5qdQ9erVMWDAgGDesmVLs3379u2D2bhx48y2derUMfMdO3aY+a5du4JZ7969zbY333yzmY8dO9bMp0+fbubWafO//fZbs23jxo3NvFatWmZeoUIFM3/88ceD2X//+1+zbdQymz17tplfe+21wcy6fAMALF26tMCPDQAtWrQw8+rVqwezFStWmG0vu+yyYFayZEmzLRUObrEQEVGsWFiIiChWLCxERBQrFhYiIooVCwsREcWKhYWIiGLFwkJERLHi9VhSqFKlSnrWWWcF806dOpnta9SoEcwWLlxotv3LX/5i5vXq1TPze++9N5hFXfOkdu3aZn7HHXeY+csvv2zmzz//fDA79dRTzbZpaWlmfvXVV5t51Hxt1apVMLvtttvMttb1dwDg1ltvNXPrOjlDhgwx20bNl6jr+0TNl8qVKwezhg0bmm1vuOGGYPa73/0Oq1ev5vVYihgPkIyRiGwEkAXgOwDZqto8tT0iIip6LCzxa6OqO1PdCSKiVOFvLEREFCsWlngpgAUislxE+uU2gYj0E5FlIrLs0KFDRdw9IqLCx6GweLVW1QwRORbAayKyVlUXJ06gqhMATADcj/ep6CQRUWHiFkuMVDXD/78dwGwA9umJ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paUFs23btplto46RiTp2qXHjxsEsal174403zHzJkiVmnp2dbebWMVmZmZlmW+t1jxgxAl988QVPm1/EuMVCRESxYmEhIqJYsbAQEVGsWFiIiChWLCxERBQrFhYiIooVCwsREcWK12NJoU2bNpnXkti1a5fZ/u677w5mp512mtm2du3aZj5z5kwzr1mzZjAbN26c2bZ///5mPmPGDDOPOlZkxIgRwcy67gcQfb2VqOeOOkZn4sSJweyuu+4y286ZM8fMly1bZuaPPPJIMKtfv77ZtmHDhmYetT5FXUvGOj5o8ODBZtu9e/cGs927d4sSO9gAAAr/SURBVJttqXBwi4WIiGLFwkJERLFiYSEiolixsBARUaxYWIiIKFYsLEREFCsWFiIiihWPY8knETkewD8B1ACgACao6qMiUhXAMwDqAdgIoJuqmgeilCpVCjVq1AjmTz75pNmXPn36BLNOnTqZba+//nozf+CBB8y8VatWwUzEvvxF+/btzfyyyy4z8w0bNph5pUqVglnUNU969epl5r179zbzQ4cOmbl1TZSNGzeabevVq2fmN954o5lbx4M88cQTZtty5cqZ+c6dO39Se+u6RFHHFllKlOB351TgXM+/bAADVbUxgLMA3CgijQHcDWChqjYAsNDfJiL6xWFhySdV3aKqK/zfWQDWAKgFoCOAKX6yKQDsTQYiop8pFpafQETqATgdwLsAaqjqFh9thRsqIyL6xWFhKSARqQDgeQC3qeqexEzdCaNyPWmUiPQTkWUisuzAgQNF0FMioqLFwlIAIlIarqhMU9VZ/u5tIpLu83QA23Nrq6oTVLW5qjY/6qijiqbDRERFiIUln8Tt8vQEgDWqmni62LkAcnYp6gXAPhUtEdHPFHc3zr9zAFwDYKWIfOjvuwfAcAAzReQ6AJsAdIt6oP3795unOh84cKDZ3trdOCMjw2z71FNPmbm1WywAnHXWWcEsarfYl19+2czHjBlj5meeeaaZX3fddcGsc+fOZtuFCxeaedTuxldffbWZd+3aNZhNnTrVbNulSxczb9CggZk//fTTwezkk08223700UdmfsUVV5h527Ztzfzyyy8PZieddJLZ9sUXXwxmpUuXNttS4WBhySdVXQIgdKDGhUXZFyKi4ohDYUREFCsWFiIiihULCxERxYqFhYiIYsXCQkREsWJhISKiWHF3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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    }
  ]
}